#!/usr/bin/python -S
"""
examples_test.py: Miscellaneous examples
"""

__author__ = 'Andy Chu'


import os
from pprint import pprint
import sys

from pan.core import cmdapp
from pan.core import params
from pan.core import json
from pan.core import util
from pan.test import testy

if __name__ == '__main__':
  # for jsonpattern package
  sys.path.insert(
      0, os.path.join(os.path.dirname(__file__), '..', 'python'))
  # Root of the project
  sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))

from tests import test_main

import jsonpattern


class JsonTest(testy.Test):

  LABELS = ['multilanguage']

  def testJson(self):
    library = {}

    def Prim2Bool(s):
      return {'true': True, 'false': False, 'null': None}[s]

    filters = {
       # A little hack to save some typing
       'escape-char': lambda c: eval(r'"\%s"' % c),
       'unicode-chr': lambda i: eval(r'u"\u%04x"' % i),

       'prim2bool': Prim2Bool,
       }

    def Add(name, pattern, desc=None):
      library[name] = jsonpattern.Pattern(
          pattern, patterns=library, filters=filters, name=name, desc=desc)

    p = r"""
        P| \\
         | $value | escape-char
        P|     {.chars abfnrtv ? " ' \ }
         | end
        """
    Add('normal-escape', p)

    p = r"""
        P| \\
         | $value | oct2int | chr
        P|     {.chars 0-7}+
         | end
        """
    Add('octal-escape', p)

    self.verify.Match(library['octal-escape'], r'\011', '\011')

    p = r"""
        P| \\x
         | $value | hex2int | chr
        P|     {.chars 0-9 a-f A-F }+
         | end
        """
    Add('hex-escape', p)

    self.verify.Match(library['hex-escape'], r'\x11', '\x11')

    p = r"""
        P| \\u
         | $value | hex2int | unicode-chr
        P|     {.chars 0-9 a-f A-F }{4}
         | end
        """
    Add('unicode-escape', p)

    self.verify.Match(library['unicode-escape'], r'\u0020', ' ')

    p = r"""
        P| "
         | $repeated
         |   choice
         |     $value
        P|       {!chars " \ }+
         |     end
         |   or
        P|     {:normal-escape}
         |   or
        P|     {:octal-escape}
         |   or
        P|     {:hex-escape}
         |   or
        P|     {:unicode-escape}
         |   end
         | end
        P| "
        """
    Add('double-quoted', p)

    p = r"""
        P| '
         | $repeated
         |   choice
         |     $value
        P|       {!chars ' \ }+
         |     end
         |   or
        P|     {:normal-escape}
         |   or
        P|     {:octal-escape}
         |   or
        P|     {:hex-escape}
         |   or
        P|     {:unicode-escape}
         |   end
         | end
        P| '
        """
    Add('single-quoted', p)

    print library['single-quoted'].AsTree()

    p = r"""
         | choice | join-strings
        P|   {:double-quoted}
         | or
        P|   {:single-quoted}
         | end
        """
    Add('string', p)

    p = r"""
        P| { \d+ |int}
        """
    Add('number', p)
    self.verify.Match(library['number'], r'3', 3)

    p = r"""
        P| { true|false|null |prim2bool}
        """
    Add('prim', p)
    self.verify.Match(library['prim'], r'true', True)
    self.verify.Match(library['prim'], r'false', False)
    self.verify.Match(library['prim'], r'null', None)

    p = r"""
         | choice
        P|   {:string}
         | or
        P|   {:number}
         | or
        P|   {:prim}
         | end
        """
    Add('value', p)

    p = r"""
        P|   \[\s*
         |   repeated 
        P|      {:value}\s*
        P|      ,?\s*  {# TODO: Alternate}
         |   end
        P|   \]\s*
        """
    Add('array', p)
    self.verify.Match(library['array'], r'[true]', [True])

    # Damn, can't capture None!!!
    #self.verify.Match(library['array'], r'[false, null]', [False, None])
    self.verify.Match(library['array'], r'[false, 3]', [False, 3])
    self.verify.Match(library['array'], r"['a', 3]", ['a', 3])

    # TODO: This shouldn't match
    self.verify.Match(library['array'], r'[falsefalse]', [False, False])

    p = r"""
        P|   \{\s*
         |   repeated | make-obj
        P|      {:string name}\s*:\s*{:value value}
        P|      ,?\s*  {# TODO: Alternate}
         |   end
        P|   \}\s*
        """
    Add('object', p)
    self.verify.Match(library['object'],
        r'{"a": true, "b":"c"}', {"a": True, 'b': 'c'})

    p = library['string']

    print p.AsTree()

    self.verify.Match(p, r"'hello'", 'hello')
    self.verify.Match(p, r"'hello\n'", 'hello\n')
    self.verify.Match(p, r"'hello\r\n'", 'hello\r\n')
    self.verify.Match(p, r"'hello\x00\n'", 'hello\x00\n')
    self.verify.Match(p, r"'hello\40\n'", 'hello \n')
    self.verify.Match(p, r"'hello\u0020\n'", 'hello \n')


if __name__ == '__main__':
  test_main.main(__import__(__name__), sys.argv[1:])
